spring源码之旅(2)_applicationcontext启动流程分析

spring源码之旅(2)_applicationcontext启动流程分析

一、           一个简单的应用

此次分析从spring的一个入门级的应用作为入口,下面是应用的代码:

TestAction(TestAction.java)

package xqq.ioc.listen1;

public static void main(String[] args)

    {

       ApplicationContext ctx=new ClassPathXmlApplicationContext("xqq//ioc//listen1//listen1_beans.xml");

       Action myAction=(Action)ctx.getBean("myAction");

       System.out.println(myAction.execute("Qiang Qiang"));

    }

Action接口代码:(Action.java)

package xqq.ioc.listen1;

public interface Action {

    String execute(String str);

}

UpperAction类代码:(UpperAction.java)

package xqq.ioc.listen1;

public class UpperAction implements Action {

    String message;

    public String execute(String str) {

       // TODO Auto-generated method stub

       return (getMessage()+str).toUpperCase();

    }

    public String getMessage() {

       return message;

    }

    public void setMessage(String message) {

       this.message = message;

    }

}

Spring配置文件(listen1_beans.xml)

<?xml version="1.0" encoding="UTF-8"?>

<beans

    xmlns="http://www.springframework.org/schema/beans"

    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

    <bean id="myAction" class="xqq.ioc.listen1.UpperAction">

       <property name="message">

           <value>Hello</value>

       </property>

    </bean>

</beans>

 

 

二、           构造方法跟踪

1.         程序进入main方法后,第一步就是通过加载一个spring xml配置文件的路径创建applicationContext

ApplicationContext ctx=new ClassPathXmlApplicationContext("xqq//ioc//listen1//listen1_beans.xml");

2.      进入ClassPathXmlApplicationContext的构造方法中

public ClassPathXmlApplicationContext(String configLocation) throws BeansException {

       this(new String[] {configLocation}, true, null);

    }

3.      由上面的代码可以看见,代码进入了一个重载的构造方法

public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)

           throws BeansException {

       super(parent);

       this.configLocations = StringUtils.trimArrayElements(configLocations);

       if (refresh) {

           refresh();

       }

    }

4.      由上面代码可见首先调用超类的构造方法,经过代码跟踪,超类构造方法的调用直至AbstractApplicationContext类的构造方法止

public AbstractApplicationContext(ApplicationContext parent) {

       this.parent = parent;

       this.resourcePatternResolver = getResourcePatternResolver();

    }

    AbstractApplicationContext构造方法中设置了parent,并且设置了resourcePatternResolver属性,查看getResourcePatternResolver()方法的源码:

protected ResourcePatternResolver getResourcePatternResolver() {

       return new PathMatchingResourcePatternResolver(this);

    }

由上面可见在AbstractApplicationContext类中默认创建了一个PathMatchingResourcePatternResolver对象来进行资源路径的解析

 

 

三、           refresh()方法刷新流程

3中调用完超类的构造方法后,最重要的就是调用refresh()方法了,refresh()方法内部实现了整个applicationContext的启动流程

Refresh()方法是在AbstractApplicationContext类内部实现的,在3中调用的其实是超类的refresh()方法

/**

     * 刷新,spring ApplicationContext初始化并工作的核心方法

     */

    public void refresh() throws BeansException, IllegalStateException {

       synchronized (this.startupShutdownMonitor) {

           //准备刷新,设置启动时间和active属性的值

           prepareRefresh();

           //在此方法内部调用抽象方法refreshBeanFactory(),并返回刷新后的beanFactory实例

           ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

           //设置beanFactory的标准特性,包括类加载器,ResourceEditorRegistrar,beanFactory增加ApplicationContextAwareProcessorbeanPost后置处理器,并调用ignoreDependencyInterface()方法设置自动装配时被忽略的类型

           prepareBeanFactory(beanFactory);

           try {

              //模板方法,供子类进行覆盖实现,本类默认实现为空          postProcessBeanFactory(beanFactory);

              //调用本类中的BeanFactoryPostProcessor集合和beanFactory中的所有后置处理器对beanFactory进行处理,如果beanFactory中的后置处理器有顺序,则按照顺序进行处理

              invokeBeanFactoryPostProcessors(beanFactory);

              //按顺序将beanFactory中的bean后置处理器全都加入至beanFactorybean后置处理器列表中

              registerBeanPostProcessors(beanFactory);

              //初始化message source,并设置其父message source

              initMessageSource();

              //初始化ApplicationEvent消息广播器

              initApplicationEventMulticaster();

              //模板方法,供子类进行覆盖实现,本类默认实现为空

              onRefresh();

              //将本类的ApplicationListener和配置beans中的ApplicationListener添加至本类的消息广播器上

              registerListeners();

              //beanFactory实例化非延迟的单例bean

              beanFactory.preInstantiateSingletons();

              //完成刷新,并发布ContextRefreshedEvent事件

              finishRefresh();

           }

           catch (BeansException ex) {

              // Destroy already created singletons to avoid dangling resources.

              beanFactory.destroySingletons();

              // Reset 'active' flag.

              cancelRefresh(ex);

              // Propagate exception to caller.

              throw ex;

           }

       }

    }

通过阅读refresh()方法代码,可以非常清楚的了解spring applicationcontext启动时的整个初始化流程:

准备刷新(记录启动时间,设置active属性为true-------à获取刷新后的beanFactory-------à

设置beanFacotry类加载器、默认属性编辑器、默认beanPost后置处理器-------à获取beanFactory中的BeanFactoryPostProcessor类型的对象,并让其对beanFactory进行后置处理-------à将配置中的beanPostProcessor类型的对象加入至beanFactory-------à初始化messageSource(如有配置,则获取配置文件中的messageSource bean对象,如没有,则创建DelegatingMessageSource让其将对messageSource的请求代理给父容器的messageSource对象处理) -------à初始化ApplicationEvent事件广播器(如有配置,则使用配置文件中所配置的消息广播器,否则默认使用SimpleApplicationEventMulticaster作为消息广播器) -------à调用模板方法onRefresh()-------à注册配置文件中所配置的消息监听器-----àbeanFactory实例化非延迟的单例bean-----à完成刷新,并发布ContextRefreshedEvent事件

 

四、           ApplicationContext内部beanFactory的创建

整个刷新过程中,创建了新的beanFactory,原有的旧beanFactory将被丢弃,obtainFreshBeanFactory()方法内部调用的refreshBeanFactory()方法实现了这种功能。refreshBeanFactory()具体由子类AbstractRefreshableApplicationContext进行实现,先将旧的beanFactory中的所有单例全都销毁,然后创建一个新的beanFactory,加载beanDefinitions,并将新的beanFactory赋给本类的beanFactory实例。

ConfigurableListableBeanFactory oldBeanFactory = null;

       synchronized (this.beanFactoryMonitor) {

           oldBeanFactory = this.beanFactory;

       }

       if (oldBeanFactory != null) {

           //销毁bean工厂中的所有单例

           oldBeanFactory.destroySingletons();

           synchronized (this.beanFactoryMonitor) {

              this.beanFactory = null;

           }

       }

 

       // Initialize fresh bean factory.

       try {

           //创建新的beanFactory

           DefaultListableBeanFactory beanFactory = createBeanFactory();

           //模板方法,供子类覆盖实现,为beanFactory提供客户端自定义的操作

           customizeBeanFactory(beanFactory);

           //beanFactory中加载bean定义

           loadBeanDefinitions(beanFactory);

           //将创建的beanFactory设置为本类的beanFactory实例

           synchronized (this.beanFactoryMonitor) {

              this.beanFactory = beanFactory;

           }

       }…………

AbstractRefreshableApplicationContext类的createBeanFactory()方法中实现了为ApplicationContext创建内部beanFactory的功能,此内部beanFactory保存了根据配置文件解析而来的各个beanBeanDefinition实例,因此ApplicationContext创建、查找bean以及对bean进行操作等功能的实现都是通过其内部beanFactory实现的。下面是此方法的代码:

protected DefaultListableBeanFactory createBeanFactory() {

       return new DefaultListableBeanFactory(getInternalParentBeanFactory());

    }

由以上代码可以看见,以applicationcontext父亲的内部beanFactory作为构造参数,创建了DefaultListableBeanFactory对象作为applicationcontext的内部beanFactory

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我会尽力解释 Spring 容器的启动流程源码。 1. 加载配置文件 Spring 容器启动时,首先会读取配置文件,通常是 `applicationContext.xml`。配置文件中定义了需要被 Spring 管理的 bean,以及它们的依赖关系等信息。 2. 创建 BeanDefinition Spring 容器会解析配置文件,创建对应的 BeanDefinition 对象。BeanDefinition 定义了 bean 的基本信息,如 bean 的类名、scope、依赖关系等等。 3. 注册 BeanDefinition 接下来,Spring 容器将创建的 BeanDefinition 注册到 BeanDefinitionRegistry 中。BeanDefinitionRegistry 是一个接口,它定义了注册、查询、删除 BeanDefinition 的方法。 4. 实例化 Bean 接下来,Spring 容器将开始实例化 bean。Spring 容器使用反射创建 bean 的实例,然后根据配置文件中的信息对 bean 进行初始化。 5. 填充属性值 在 bean 实例化之后,Spring 容器会开始填充属性值。Spring 容器会根据配置文件中的信息,自动为 bean 填充属性值。这些属性可以是基本类型、引用类型、集合类型等等。 6. 调用 BeanPostProcessor 在填充完属性值之后,Spring 容器会调用 BeanPostProcessor 的方法。BeanPostProcessor 是一个接口,它定义了在 bean 实例化和初始化过程中的回调方法。通过实现 BeanPostProcessor,我们可以在 bean 实例化和初始化的过程中做一些自定义的操作。 7. 初始化 Bean 在填充完属性值和调用 BeanPostProcessor 之后,Spring 容器会调用 bean 的初始化方法。初始化方法可以是 init-method 指定的方法,也可以是实现了 InitializingBean 接口的 afterPropertiesSet() 方法。 8. 注册销毁方法 当 bean 的生命周期结束时,Spring 容器会调用它的销毁方法。销毁方法可以是 destroy-method 指定的方法,也可以是实现了 DisposableBean 接口的 destroy() 方法。 以上就是 Spring 容器启动流程的大概过程。其中,BeanDefinition、BeanPostProcessor、InitializingBean、DisposableBean 等接口和类都是 Spring 框架中提供的,它们为我们提供了更加灵活的配置和扩展方式。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值